/**
 ******************************************************************************
 * @file    zb32l03x_hal_uart_irda.c
 * @author  MCU Application Team
 * @Version V0.0.1
 * @Date    2022/12/30
 * @brief   UART IrDA HAL module driver.
 @verbatim
 ******************************************************************************
 **/
#include "zb32l03x_hal.h"

#if defined(HAL_UART_IRDA_MODULE_ENABLED)
/** @addtogroup UART_IrDA
  * @brief UART_IrDA HAL module driver.
  * @{
  */

//=============================================================================
//                         Constant Definition
//=============================================================================

/**
  * @EVEN Parity check data.
  * @{
  */
static const uint8_t ParityTable256[256] =
{
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    1, 0,   0, 1,   0, 1,   1, 0,   0, 1,   1, 0,   1, 0,   0, 1,
    0, 1,   1, 0,   1, 0,   0, 1,   1, 0,   0, 1,   0, 1,   1, 0
};

/** End of Parity check data
 * @}
 */

#define UART_IRDA_BIT0_Msk               (0x01U)


//=============================================================================
//                          Macro Definition
//=============================================================================

//=============================================================================
//                        Structure Definition
//=============================================================================

//=============================================================================
//                       Global Data Definition
//=============================================================================

//=============================================================================
//                     Private Function Definition
//=============================================================================

/** @addtogroup UART_Private_Functions
  * @{
  */

/**
 * @brief  Configures the UART peripheral.
 * @param  huart: pointer to a UART_IRDAHandleTypeDef structure that contains
 *                the configuration information for the specified UART module.
 * @retval None
 */
static void _UART_IRDA_SetConfig(UART_IRDA_HandleTypeDef *hirda)
{
    uint32_t    bauddiv = 0U;
    uint32_t    pclk    = 0U;

    /*------- UART-associated registers setting : SCON Configuration ------*/
    /* Configure the UART Word Length and mode:
       Set the DBAUD bits according to hirda->Init.BaudDouble value
       Set the SM bits according to hirda->Init.WordLength value
       Set REN bits according to hirda->Init.Mode value */
    MODIFY_REG(hirda->Instance->SCON,
               (UART_SCON_DBAUD | UART_SCON_SM0_SM1 | UART_SCON_REN),
               hirda->Init.BaudDouble | hirda->Init.WordLength | hirda->Init.Mode);

    MODIFY_REG(hirda->Instance->SADDR,
               (UART_SADDR_SADDR),
               (hirda->Init.SlaveAddr & UART_SADDR_SADDR));

    MODIFY_REG(hirda->Instance->SADEN,
               (UART_SADEN_SADEN),
               (hirda->Init.SlaveAddrMask & UART_SADEN_SADEN));

    MODIFY_REG(hirda->Instance->IRDACR,
               (UART_IRDACR_IRLPMODE | UART_IRDACR_IRRXINV | UART_IRDACR_IRTXINV),
               (hirda->Init.PowerMode | hirda->Init.ReceInversion | hirda->Init.TranInversion));

    /*-------------------------- UART BAUDCR Configuration ---------------------*/
    pclk = HAL_RCC_GetPCLKFreq();

    bauddiv = ((((hirda->Init.BaudDouble == UART_IRDA_BAUDDOUBLE_ENABLE)? 2U : 1U) * pclk) / (32U * (hirda->Init.BaudRate))) - 1U;

    MODIFY_REG(hirda->Instance->BAUDCR,
               (UART_BAUDCR_BRG | UART_BAUDCR_SELF_BRG),
               (bauddiv | ((~hirda->Init.ProgTimer) & UART_BAUDCR_SELF_BRG)));

    if( hirda->Init.PowerMode == UART_IRDA_NORMAL_MODE )
    {
        MODIFY_REG(hirda->Instance->IRDACR,
                   UART_IRDACR_PSC,
                   (1 << UART_IRDACR_PSC_Pos));
    }
    else
    {
        MODIFY_REG(hirda->Instance->IRDACR,
                   UART_IRDACR_PSC,
                   (hirda->Init.Prescaler << UART_IRDACR_PSC_Pos));
    }

    return;
}


/**
 * @brief  This function handles UART Communication Timeout.
 * @param  hirda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART module.
 * @param  Flag: specifies the UART flag to check.
 * @param  Status: The new Flag status (SET or RESET).
 * @param  Tickstart Tick start value
 * @param  Timeout: Timeout duration
 * @retval HAL status
 */
static HAL_StatusTypeDef
_UART_IRDA_WaitOnFlagUntilTimeout(UART_IRDA_HandleTypeDef *hirda,
                                  uint32_t Flag,
                                  FlagStatus Status,
                                  uint32_t Tickstart,
                                  uint32_t Timeout)
{
    if( Timeout == 0U )
    {
        return HAL_TIMEOUT;
    }

    while( (__HAL_UART_IRDA_GET_FLAG(hirda, Flag) ? SET : RESET) == Status )
    {
        if( (Timeout != HAL_MAX_DELAY) &&
            ((HAL_GetTick() - Tickstart) > Timeout) )
        {
            /* Disable TXE, RXNE interrupts for the interrupt process */
            __HAL_UART_IRDA_DISABLE_IT(hirda, (UART_IRDA_IT_TIEN | UART_IRDA_IT_RIEN));

            return HAL_TIMEOUT;
        }

        if( __HAL_UART_IRDA_GET_FLAG(hirda, UART_IRDA_FLAG_FE) == SET )
        {
            hirda->ErrorCode |= HAL_UART_IRDA_ERROR_FE;

            __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_FE);
        }
    }

    return HAL_OK;
}


/**
 * @brief  This function handles UART IrDA Addressing Communication Timeout.
 * @param  hirda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART module.
 * @param  Tickstart Tick start value
 * @param  Timeout: Timeout duration
 * @retval HAL status
 */
static HAL_StatusTypeDef
_UART_IRDA_WaitAddressingFlagUntilTimeout(UART_IRDA_HandleTypeDef *hirda,
                                          uint32_t Tickstart,
                                          uint32_t Timeout)
{
    __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_RXNE);

    SET_BIT(hirda->Instance->SCON, UART_SCON_SM2);

    while( (__HAL_UART_IRDA_GET_FLAG(hirda, UART_IRDA_FLAG_RXNE) == RESET) )
    {
        if( Timeout != HAL_MAX_DELAY && ((HAL_GetTick() - Tickstart) > Timeout) )
        {
            CLEAR_BIT(hirda->Instance->SCON, UART_SCON_SM2);

            return HAL_TIMEOUT;
        }
    }

    __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_RXNE);

    CLEAR_BIT(hirda->Instance->SCON, UART_SCON_SM2);

    return HAL_OK;
}

/**
  * @brief  The UART IrDA module uses interrupt handling to send data once.
  * @param  hirda   Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                 the configuration information for the specified UART module.
  * @retval HAL status
  */
static HAL_StatusTypeDef
_UART_IRDA_Transmit_IT(UART_IRDA_HandleTypeDef *hirda)
{
    if( hirda->gState != HAL_UART_IRDA_STATE_BUSY_TX )  //Check module interrupt source is normally.
    {
        __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_TC);

        __HAL_UART_IRDA_DISABLE_IT(hirda, UART_IRDA_IT_TIEN);

        return HAL_BUSY;
    }

    hirda->TxXferCount--;
    hirda->pTxBuffPtr++;

    if( hirda->TxXferCount == 0U )                  //Count minus and determine if the transfer is complete.
    {
        __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_TC);

        __HAL_UART_IRDA_DISABLE_IT(hirda, UART_IRDA_IT_TIEN);

        hirda->gState = HAL_UART_IRDA_STATE_READY;

        return HAL_OK;
    }

    __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_TC);

    if( hirda->Init.WordLength == UART_IRDA_WORDLENGTH_9B )
    {
        if( hirda->Init.Parity == UART_IRDA_PARITY_NONE )
        {
            CLEAR_BIT(hirda->Instance->SCON, UART_SCON_TB8);

            WRITE_REG(hirda->Instance->SBUF, *hirda->pTxBuffPtr);

        }
        else if( hirda->Init.Parity == UART_IRDA_PARITY_EVEN )
        {
            (ParityTable256[*hirda->pTxBuffPtr])
            ? MODIFY_REG(hirda->Instance->SCON, UART_SCON_TB8, 0)
            : MODIFY_REG(hirda->Instance->SCON, UART_SCON_TB8, UART_SCON_TB8);

            WRITE_REG(hirda->Instance->SBUF, *hirda->pTxBuffPtr);
        }
        else if( hirda->Init.Parity == UART_IRDA_PARITY_ODD )
        {
            (ParityTable256[*hirda->pTxBuffPtr])
            ? MODIFY_REG(hirda->Instance->SCON, UART_SCON_TB8, UART_SCON_TB8)
            : MODIFY_REG(hirda->Instance->SCON, UART_SCON_TB8, 0);

            WRITE_REG(hirda->Instance->SBUF, *hirda->pTxBuffPtr);
        }
        else
        {
            hirda->ErrorCode |= HAL_UART_IRDA_ERROR_CONFIG;

            __HAL_UART_IRDA_DISABLE_IT(hirda, UART_IRDA_IT_TIEN);

            return HAL_ERROR;
        }

    }
    else
    {
        WRITE_REG(hirda->Instance->SBUF, *hirda->pTxBuffPtr);
    }

    return HAL_OK;
}

/**
  * @brief  The UART IrDA module uses interrupt handling to receive data once.
  * @param  hirda   Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                 the configuration information for the specified UART module.
  * @retval HAL status
  */
static HAL_StatusTypeDef _UART_IRDA_Receive_IT( UART_IRDA_HandleTypeDef *hirda)
{
    __IO uint8_t tmp    = 0U;
    __IO uint8_t check  = 0U;

    /* Check module interrupt source is normally. */
    if( hirda->RxState != HAL_UART_IRDA_STATE_BUSY_RX &&
        hirda->RxState != HAL_UART_IRDA_STATE_BUSY_RX_ADDRESS )
    {
        __HAL_UART_IRDA_DISABLE_IT(hirda, UART_IRDA_IT_RIEN);

        __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_RXNE);

        return HAL_BUSY;
    }

    if( hirda->RxState == HAL_UART_IRDA_STATE_BUSY_RX_ADDRESS )
    {
        __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_RXNE);

        CLEAR_BIT(hirda->Instance->SCON, UART_SCON_SM2);

        hirda->RxState = HAL_UART_IRDA_STATE_BUSY_RX;

        return HAL_OK;
    }

    tmp  = READ_REG(hirda->Instance->SBUF);

    __HAL_UART_IRDA_CLEAR_FLAG(hirda, UART_IRDA_FLAG_RXNE);

    *hirda->pRxBuffPtr = tmp;

    hirda->pRxBuffPtr++;

    hirda->RxXferCount--;

    if( hirda->Init.WordLength == UART_IRDA_WORDLENGTH_9B )
    {
        if( hirda->Init.Parity == UART_IRDA_PARITY_EVEN )
        {
            READ_BIT(hirda->Instance->SCON, UART_SCON_RB8) ? (check = 1U) : (check = 0U);
        }
        else if( hirda->Init.Parity == UART_IRDA_PARITY_ODD )
        {
            READ_BIT(hirda->Instance->SCON, UART_SCON_RB8) ? (check = 0U) : (check = 1U);
        }

        if( check != ParityTable256[tmp] )
        {
            hirda->ErrorCode |= HAL_UART_IRDA_ERROR_PARITY;
        }
    }

    if( hirda->RxXferCount == 0U )
    {
        __HAL_UART_IRDA_DISABLE_IT(hirda, UART_IRDA_IT_RIEN);
        __HAL_UART_IRDA_DISABLE_IT(hirda, UART_IRDA_IT_FEEN);

        hirda->RxState = HAL_UART_IRDA_STATE_READY;
    }

    return HAL_OK;
}


/** End of UART_Private_Functions
 * @}
 */

//=============================================================================
//                          Public Function
//=============================================================================

/** @defgroup UART_Exported_Functions UART Exported Functions
 * @{
 */

/**
 * @brief  Initializes the UART IrDA mode according to the specified parameters in
 *         the UART_IRDA_InitTypeDef and create the associated handle.
 * @param  pHIrda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART module.
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_UART_IrDA_Init(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Check the UART handle allocation */
    if( pHIrda == NULL || pHIrda->Instance == NULL )
    {
        return HAL_ERROR;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_BAUDDOUBLE(pHIrda->Init.BaudDouble));
    assert_param(IS_UART_IRDA_MODE(pHIrda->Init.Mode));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_POWERMODE(pHIrda->Init.PowerMode));
    assert_param(IS_UART_IRDA_PROGTIMER(pHIrda->Init.ProgTimer));
    assert_param(IS_UART_IRDA_TRANINVERSION(pHIrda->Init.TranInversion));
    assert_param(IS_UART_IRDA_RECEINVERSION(pHIrda->Init.ReceInversion));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));
    assert_param(IS_UART_IRDA_PRESCALER(pHIrda->Init.Prescaler));

    if( pHIrda->gState == HAL_UART_IRDA_STATE_RESET )
    {
        /* Allocate lock resource and initialize it */
        pHIrda->Lock = HAL_UNLOCKED;

        /* Init the low level hardware */
        HAL_UART_IrDA_MspInit(pHIrda);
    }

    pHIrda->gState = HAL_UART_IRDA_STATE_BUSY;

    __HAL_UART_IRDA_DISABLE(pHIrda);

    /* Set the UART Communication parameters */
    _UART_IRDA_SetConfig(pHIrda);

    __HAL_UART_IRDA_ENABLE(pHIrda);

    /* Initialize the UART IrDA state */
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->gState      = HAL_UART_IRDA_STATE_READY;
    pHIrda->RxState     = HAL_UART_IRDA_STATE_READY;

    return HAL_OK;
}


/**
 * @brief  DeInitializes the UART peripheral.
 * @param  pHIrda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART IrDA module.
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_UART_IrDA_DeInit (UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Check the UART handle allocation */
    if( pHIrda == NULL || pHIrda->Instance == NULL )
    {
        return HAL_ERROR;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));

    pHIrda->gState = HAL_UART_IRDA_STATE_BUSY;

    /* DeInit the low level hardware */
    HAL_UART_IrDA_MspDeInit(pHIrda);

    /* DeInitialize the UART IrDA state */
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->gState      = HAL_UART_IRDA_STATE_READY;
    pHIrda->RxState     = HAL_UART_IRDA_STATE_READY;

    pHIrda->Lock = HAL_UNLOCKED;

    return HAL_OK;
}


/**
 * @brief  UART IRDA MSP Init.
 * @param  pHIrda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART IrDA module.
 * @retval None
 */
__weak void HAL_UART_IrDA_MspInit(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);
    /* NOTE: This function should not be modified, when the callback is needed,
             the HAL_UART_MspInit could be implemented in the user file
     */

}


/**
 * @brief  UART IRDA MSP DeInit.
 * @param  pHIrda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART IrDA module.
 * @retval None
 */
__weak void HAL_UART_IrDA_MspDeInit(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);
    /* NOTE: This function should not be modified, when the callback is needed,
             the HAL_UART_MspDeInit could be implemented in the user file
     */
}


/**
 * @brief  Calculate period value of BASETIM if programable timer function is enabled.
 * @param  pHIrda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART IrDA module.
 * @retval period value of BASETIM
 */
uint16_t HAL_UART_IRDA_CalcProgTimerPeriod(UART_IRDA_HandleTypeDef *pHIrda)
{
    uint16_t period = 0U;

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));

    period = 0x10000UL - ((((pHIrda->Init.BaudDouble == UART_IRDA_BAUDDOUBLE_ENABLE) ? 2U : 1U) * HAL_RCC_GetPCLKFreq()) / (32U * (pHIrda->Init.BaudRate)));

    return period;
}




/**
 * @brief  Sends an amount of data in blocking mode.
 * @param  pHIrda: pointer to a UART_IRDA_HandleTypeDef structure that contains
 *                the configuration information for the specified UART IrDA module.
 * @param  pData: Pointer to data buffer
 * @param  Size: Amount of data to be sent
 * @param  Timeout: Timeout duration
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_UART_IRDA_Transmit(UART_IRDA_HandleTypeDef *pHIrda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    HAL_StatusTypeDef   rval        = HAL_OK;
    uint32_t            tickstart   = 0U;

    if( !pHIrda || !pData || !Size || !Timeout )
    {
        return HAL_ERROR;
    }

    if( pHIrda->gState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));

    __HAL_LOCK(pHIrda);

    pHIrda->gState      = HAL_UART_IRDA_STATE_BUSY_TX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->TxXferCount = Size;
    pHIrda->TxXferSize  = Size;
    pHIrda->pTxBuffPtr  = pData;

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

    tickstart = HAL_GetTick();

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    while( pHIrda->TxXferCount )
    {
        /* Set parity bit value */
        if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B )
        {
            if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
            {
                ParityTable256[*pHIrda->pTxBuffPtr]
                ? SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
                : CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
            }
            else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
            {
                ParityTable256[*pHIrda->pTxBuffPtr]
                ? CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
                : SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
            }
            else
            {
                CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
            }
        }
        else
        {
            CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }

        /* Send a data */
        WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);

        /* Wait for the data to finish sending */
        rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_TC, RESET, tickstart, Timeout);
        if( rval != HAL_OK )
        {
            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_TIMEOUT;

            pHIrda->gState = HAL_UART_IRDA_STATE_READY;

            __HAL_UNLOCK(pHIrda);

            return rval;
        }

        __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

        pHIrda->TxXferCount--;
        pHIrda->pTxBuffPtr++;
    }

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

    pHIrda->gState = HAL_UART_IRDA_STATE_READY;

    __HAL_UNLOCK(pHIrda);

    return rval;
}


/**
  * @brief  Receive an amount of data in blocking mode.
  * @param  pHIrda    Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                 the configuration information for the specified UART IrDA module.
  * @param  pData     Pointer to data buffer.
  * @param  Size    Amount of data elements to be received.
  * @param  Timeout Timeout duration.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Receive(UART_IRDA_HandleTypeDef *pHIrda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    HAL_StatusTypeDef   rval        = HAL_OK;
    uint32_t            tickstart   = 0U;
    uint8_t             check       = 0U;

    if( !pHIrda || !pData || !Size || !Timeout )
    {
        return HAL_ERROR;
    }

    if( pHIrda->RxState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));

    __HAL_LOCK(pHIrda);

    pHIrda->RxState     = HAL_UART_IRDA_STATE_BUSY_RX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->RxXferCount = Size;
    pHIrda->RxXferSize  = Size;
    pHIrda->pRxBuffPtr  = pData;

    #if defined(UART_INTDIS_RIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_FE);
    #endif  /* End of UART_INTDIS_RIDIS */

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, (UART_IRDA_IT_RIEN | UART_IRDA_IT_FEEN));

    tickstart = HAL_GetTick();

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_RXNE);

    while( pHIrda->RxXferCount )
    {
        /* Wait for the data to finish receive */
        rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_RXNE, RESET, tickstart, Timeout);
        if( rval != HAL_OK )
        {
            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_TIMEOUT;

            pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

            __HAL_UNLOCK(pHIrda);

            return rval;
        }

        *pHIrda->pRxBuffPtr = (uint8_t)pHIrda->Instance->SBUF;

        __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_RXNE);

        /* Check parity bit */
        if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
            pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
        {
            /* Read check bit */
            if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
            {
                READ_BIT(pHIrda->Instance->SCON, UART_SCON_RB8) ? (check = 1U) : (check = 0U);

            }
            else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
            {
                READ_BIT(pHIrda->Instance->SCON, UART_SCON_RB8) ? (check = 0U) : (check = 1U);
            }
            else
            {
                pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_CONFIG;
            }

            /* Check whether the parity bit data is consistent */
            if( check != ParityTable256[*pHIrda->pRxBuffPtr] )
            {
                pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_PARITY;
            }
        }

        pHIrda->RxXferCount--;
        pHIrda->pRxBuffPtr++;
    }

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, (UART_IRDA_IT_FEEN | UART_IRDA_IT_RIEN));

    __HAL_UNLOCK(pHIrda);

    pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

    if( pHIrda->ErrorCode == HAL_UART_IRDA_ERROR_NONE )
    {
        return rval;
    }
    else
    {
        return HAL_ERROR;
    }
}


/**
  * @brief  Send an amount of data in non-blocking mode.
  * @param  pHIrda    Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                 the configuration information for the specified UART IrDA module.
  * @param  pData   Pointer to data buffer.
  * @param  Size    Amount of data elements to be sent.
  * @retval HAL status
  * @note   The USART errors are not managed to avoid the overrun error.
  */
HAL_StatusTypeDef HAL_UART_IRDA_Transmit_IT(UART_IRDA_HandleTypeDef *pHIrda, uint8_t *pData, uint16_t Size)
{
    if( !pHIrda || !pData || !Size )
    {
        return HAL_ERROR;
    }

    if( pHIrda->gState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->gState      = HAL_UART_IRDA_STATE_BUSY_TX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->TxXferCount = Size;
    pHIrda->TxXferSize  = Size;
    pHIrda->pTxBuffPtr  = pData;

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_DISABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

    __HAL_UNLOCK(pHIrda);

    /* Send a data to activate the send process */
    if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
        {
            ParityTable256[*pHIrda->pTxBuffPtr] ?
            SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8) :
            CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }
        else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
        {
            ParityTable256[*pHIrda->pTxBuffPtr] ?
            CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8) :
            SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }
        else    /* Handle init info have error to stop send process */
        {
            __HAL_LOCK(pHIrda);

            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_CONFIG;

            __HAL_UART_IRDA_DISABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

            pHIrda->gState = HAL_UART_IRDA_STATE_ERROR;

            __HAL_UNLOCK(pHIrda);

            return HAL_ERROR;
        }
    }

    WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);

    return HAL_OK;
}


/**
  * @brief  Receive an amount of data in non-blocking mode.
  * @param  pHIrda    Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                 the configuration information for the specified UART IrDA module.
  * @param  pData   Pointer to data buffer (uint8 or uint16 data elements).
  * @param  Size    Amount of data elements (uint8 or uint16) to be received.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Receive_IT(UART_IRDA_HandleTypeDef *pHIrda, uint8_t *pData, uint16_t Size)
{
    if( !pHIrda || !pData || !Size )
    {
        return HAL_ERROR;
    }

    if( pHIrda->RxState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->RxState     = HAL_UART_IRDA_STATE_BUSY_RX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->RxXferCount = Size;
    pHIrda->RxXferSize  = Size;
    pHIrda->pRxBuffPtr  = pData;

    #if defined(UART_INTDIS_RIDIS)
    __HAL_UART_IRDA_DISABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    __HAL_UART_IRDA_DISABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_FE);
    #endif  /* End of UART_INTDIS_RIDIS */

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_RIEN);
    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_FEEN);

    __HAL_UNLOCK(pHIrda);

    return HAL_OK;
}


/**
  * @brief  Abort ongoing transfer.
  * @param  pHIrda UART IrDA handle.
  * @note   This procedure could be used for aborting any ongoing transfer.
  *         This procedure is executed : when exiting function, Abort is considered as completed.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Abort(UART_IRDA_HandleTypeDef *pHIrda)
{
    if( !pHIrda )
    {
        return HAL_ERROR;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_FE);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, UART_IRDA_IT_MASK);
    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, (UART_IRDA_FLAG_TC | UART_IRDA_FLAG_RXNE | UART_IRDA_FLAG_FE));

    pHIrda->TxXferCount = 0U;
    pHIrda->RxXferCount = 0U;

    pHIrda->gState  = HAL_UART_IRDA_STATE_READY;
    pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

    __HAL_UNLOCK(pHIrda);

    HAL_UART_IRDA_AbortCpltCallback(pHIrda);

    return HAL_OK;
}


/**
  * @brief  Abort ongoing transmit data.
  * @param  pHIrda UART IRDA handle.
  * @note   This procedure could be used for aborting any ongoing transfer.
  *         This procedure is executed : when exiting function, Abort is considered as completed.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_IRDA_AbortTransmit(UART_IRDA_HandleTypeDef *pHIrda)
{
    if( !pHIrda )
    {
        return HAL_ERROR;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, UART_IRDA_IT_TIEN);
    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    pHIrda->TxXferCount = 0U;

    pHIrda->gState = HAL_UART_IRDA_STATE_READY;

    __HAL_UNLOCK(pHIrda);

    HAL_UART_IRDA_AbortTransmitCpltCallback(pHIrda);

    return HAL_OK;
}


/**
  * @brief  Abort ongoing receive data.
  * @param  pHIrda UART IRDA handle.
  * @note   This procedure could be used for aborting any ongoing transfer.
  *         This procedure is executed : when exiting function, Abort is considered as completed.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_IRDA_AbortReceive(UART_IRDA_HandleTypeDef *pHIrda)
{
    if( !pHIrda )
    {
        return HAL_ERROR;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));

    #if defined(UART_INTDIS_RIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_FE);
    #endif  /* End of UART_INTDIS_RIDIS */

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, (UART_IRDA_IT_RIEN | UART_IRDA_IT_FEEN) );
    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, (UART_IRDA_FLAG_RXNE | UART_IRDA_FLAG_FE) );

    pHIrda->RxXferCount = 0U;

    pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

    __HAL_UNLOCK(pHIrda);

    HAL_UART_IRDA_AbortReceiveCpltCallback(pHIrda);

    return HAL_OK;
}



/**
  * @brief  This function handles UART IrDA interrupt request.
  * @param  pHUsart  Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                the configuration information for the specified UART IrDA module.
  * @retval None
  */
void HAL_UART_IRDA_IRQHandler(UART_IRDA_HandleTypeDef *pHIrda)
{
    HAL_StatusTypeDef   rval        = HAL_OK;
    uint32_t            regiten     = pHIrda->Instance->SCON;
    uint32_t            regitsr     = pHIrda->Instance->INTSR;
    uint32_t            errorflag   = (pHIrda->Instance->INTSR & UART_INTSR_FE);

    /* Receive data handle */
    if( (regiten & UART_SCON_RIEN) &&
        (regitsr & UART_INTSR_RI) )
    {
        rval = _UART_IRDA_Receive_IT(pHIrda);

        if( rval == HAL_ERROR )
        {
            HAL_UART_IRDA_ErrorCallback(pHIrda);
        }

        if( rval == HAL_OK && (!pHIrda->RxXferCount) )
        {
            HAL_UART_IRDA_RxCpltCallback(pHIrda);
        }

        if( !errorflag )
        {
            return;
        }
    }

    /* FE handle */
    if( errorflag &&
        (regiten & UART_SCON_FEEN) )
    {
        __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_FE);

        pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_FE;

        HAL_UART_IRDA_ErrorCallback(pHIrda);

        return;
    }

    /* Send data handle */
    if( (regiten & UART_SCON_TIEN) &&
        (regitsr & UART_INTSR_TI) )
    {
        rval = _UART_IRDA_Transmit_IT(pHIrda);

        if( rval == HAL_OK && (!pHIrda->TxXferCount) )
        {
            HAL_UART_IRDA_TxCpltCallback(pHIrda);
        }
    }

    return;
}



/**
  * @brief  Tx Transfer completed callbacks.
  * @param  pHIrda   Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                the configuration information for the specified UART IrDA module.
  * @retval None
  */
__weak void HAL_UART_IRDA_TxCpltCallback(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);
    /* NOTE: This function should not be modified, when the callback is needed,
            the HAL_UART_IRDA_TxCpltCallback could be implemented in the user file
    */
}


/**
  * @brief  Rx Transfer completed callbacks.
  * @param  pHIrda   Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                the configuration information for the specified UART IrDA module.
  * @retval None
  */
__weak void HAL_UART_IRDA_RxCpltCallback(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);
    /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_UART_IRDA_RxCpltCallback could be implemented in the user file
    */
}


/**
  * @brief  UART IrDA error callbacks.
  * @param  pHIrda   Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                the configuration information for the specified UART IrDA module.
  * @retval None
  */
__weak void HAL_UART_IRDA_ErrorCallback(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);
    /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_UART_IRDA_ErrorCallback could be implemented in the user file
    */
}


/**
  * @brief  UART IrDA Abort Complete callback.
  * @param  pHIrda UART Irda handle.
  * @retval None
  */
__weak void HAL_UART_IRDA_AbortCpltCallback(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);

    /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_IRDA_AbortCpltCallback can be implemented in the user file.
    */
}


/**
  * @brief  UART IrDA Transmit Abort Complete callback.
  * @param  pHIrda UART IrDA handle.
  * @retval None
  */
__weak void HAL_UART_IRDA_AbortTransmitCpltCallback(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);

    /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_IRDA_AbortTransmitCpltCallback can be implemented in the user file.
    */
}


/**
  * @brief  UART Receive Abort Complete callback.
  * @param  pHIrda UART IrDA handle.
  * @retval None
  */
__weak void HAL_UART_IRDA_AbortReceiveCpltCallback(UART_IRDA_HandleTypeDef *pHIrda)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHIrda);

    /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_IRDA_AbortReceiveCpltCallback can be implemented in the user file.
    */

}


/**
  * @brief  Send and receive an amount of data in blocking mode.
  * @param  pHIrda     Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                  the configuration information for the specified UART IrDA module.
  * @param  ptxBuff  Pointer to transmit data buff.
  * @param  txSize   Amount of data elements to be sent.
  * @param  prxBuff  Pointer to receive data buff.
  * @param  rxSize   Amount of data elements to be received.
  * @param  Timeout  Timeout duration.
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_UART_IRDA_TransmitReceive(UART_IRDA_HandleTypeDef *pHIrda,
                                                uint8_t *ptxBuff, uint16_t txSize,
                                                uint8_t *prxBuff, uint16_t rxSize, uint32_t Timeout)
{
    HAL_StatusTypeDef rval = HAL_OK;

    uint32_t tickstart  = 0U;
    uint8_t  check      = 0U;

    if( !pHIrda || !Timeout ||
        !ptxBuff || !txSize ||
        !prxBuff || !rxSize )
    {
        return HAL_ERROR;
    }

    if( pHIrda->gState != HAL_UART_IRDA_STATE_READY ||
        pHIrda->RxState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->gState      = HAL_UART_IRDA_STATE_BUSY_TX;
    pHIrda->RxState     = HAL_UART_IRDA_STATE_BUSY_RX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->TxXferCount = txSize;
    pHIrda->TxXferSize  = txSize;
    pHIrda->RxXferCount = rxSize;
    pHIrda->RxXferSize  = rxSize;
    pHIrda->pTxBuffPtr  = ptxBuff;
    pHIrda->pRxBuffPtr  = prxBuff;

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, (UART_IRDA_IT_RIEN | UART_IRDA_IT_TIEN));

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_FLAG_RXNE);
    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_FLAG_TC);

    tickstart = HAL_GetTick();

    /* Send a data */
    if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
        {
            ParityTable256[*pHIrda->pTxBuffPtr]
            ? SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
            : CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }
        else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
        {
            ParityTable256[*pHIrda->pTxBuffPtr]
            ? CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
            : SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }
    }
    WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);
    pHIrda->TxXferCount--;
    pHIrda->pTxBuffPtr++;

    while( (pHIrda->TxXferCount || pHIrda->RxXferCount) &&
           ((HAL_GetTick() - tickstart) < Timeout) )
    {
        if( __HAL_UART_IRDA_GET_FLAG(pHIrda, UART_IRDA_FLAG_RXNE) &&
            pHIrda->RxXferCount )
        {
            *pHIrda->pRxBuffPtr = (uint8_t)pHIrda->Instance->SBUF;

            __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_RXNE);

            if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
                pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
            {
                if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
                {
                    READ_BIT(pHIrda->Instance->SCON, UART_SCON_RB8) ? (check = 1U) : (check = 0U);
                }
                else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
                {
                    READ_BIT(pHIrda->Instance->SCON, UART_SCON_TB8) ? (check = 0U) : (check = 1U);
                }

                if( ParityTable256[*pHIrda->pRxBuffPtr] != check )
                {
                    pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_PARITY;
                }
            }

            pHIrda->RxXferCount--;
            pHIrda->pRxBuffPtr++;
        }

        if( __HAL_UART_IRDA_GET_FLAG(pHIrda, UART_IRDA_FLAG_TC) &&
            pHIrda->TxXferCount )
        {
            __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

            if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
                pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
            {
                if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
                {
                    ParityTable256[*pHIrda->pTxBuffPtr]
                    ? SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
                    : CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
                }
                else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
                {
                    ParityTable256[*pHIrda->pTxBuffPtr]
                    ? CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
                    : SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
                }
                else
                {
                    CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
                }
            }

            WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);

            pHIrda->TxXferCount--;
            pHIrda->pTxBuffPtr++;
        }
    }

    rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_TC, RESET, tickstart, Timeout);

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, (UART_IRDA_IT_RIEN | UART_IRDA_IT_TIEN));

    pHIrda->gState  = HAL_UART_IRDA_STATE_READY;
    pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

    if( rval != HAL_OK ||
        pHIrda->TxXferCount ||
        pHIrda->RxXferCount )
    {
        rval = HAL_TIMEOUT;
    }
    if( pHIrda->ErrorCode != HAL_UART_IRDA_ERROR_NONE )
    {
        rval = HAL_ERROR;
    }

    __HAL_UNLOCK(pHIrda);

    return rval;
}


/**
  * @brief  Data is sent until it is received in blocking mode.
  * @param  pHIrda     Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                  the configuration information for the specified UART IrDA module.
  * @param  ptxBuff  Pointer to transmit data buff.
  * @param  txSize   Amount of data elements to be sent.
  * @param  prxBuff  Pointer to receive data buff.
  * @param  rxSize   Amount of data elements to be received.
  * @param  Timeout  Timeout duration.
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_UART_IRDA_ReceiveTransmit(UART_IRDA_HandleTypeDef *pHIrda,
                                                uint8_t *ptxBuff, uint16_t txSize,
                                                uint8_t *prxBuff, uint16_t rxSize,
                                                uint32_t Timeout)
{
    HAL_StatusTypeDef rval = HAL_OK;

    uint32_t tickstart  = 0U;
    uint8_t  check      = 0U;

    if( !pHIrda || !Timeout ||
        !ptxBuff || !txSize ||
        !prxBuff || !rxSize )
    {
        return HAL_ERROR;
    }

    if( pHIrda->gState != HAL_UART_IRDA_STATE_READY ||
        pHIrda->RxState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->gState      = HAL_UART_IRDA_STATE_BUSY_TX;
    pHIrda->RxState     = HAL_UART_IRDA_STATE_BUSY_RX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->TxXferCount = txSize;
    pHIrda->TxXferSize  = txSize;
    pHIrda->RxXferCount = rxSize;
    pHIrda->RxXferSize  = rxSize;
    pHIrda->pTxBuffPtr  = ptxBuff;
    pHIrda->pRxBuffPtr  = prxBuff;

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    __HAL_UART_IRDA_ENABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, (UART_IRDA_IT_RIEN | UART_IRDA_IT_TIEN));

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_FLAG_RXNE);
    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_FLAG_TC);

    tickstart = HAL_GetTick();

    /* Wait receive a data */
    rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_RXNE, RESET, tickstart, Timeout);
    if( rval != HAL_OK )
    {
        pHIrda->ErrorCode   |= HAL_UART_IRDA_ERROR_TIMEOUT;
        pHIrda->gState      = HAL_UART_IRDA_STATE_READY;
        pHIrda->RxState     = HAL_UART_IRDA_STATE_READY;

        __HAL_UNLOCK(pHIrda);

        return HAL_TIMEOUT;
    }

    *pHIrda->pRxBuffPtr = (uint8_t)pHIrda->Instance->SBUF;

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_FLAG_RXNE);

    if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
        {
            READ_BIT(pHIrda->Instance->SCON, UART_SCON_RB8) ? (check = 1U) : (check = 0U);
        }
        else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
        {
            READ_BIT(pHIrda->Instance->SCON, UART_SCON_TB8) ? (check = 0U) : (check = 1U);
        }

        if( ParityTable256[*pHIrda->pRxBuffPtr] != check )
        {
            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_PARITY;
        }
    }

    pHIrda->RxXferCount--;
    pHIrda->pRxBuffPtr++;

    /* Send a data */
    if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
        {
            ParityTable256[*pHIrda->pTxBuffPtr]
            ? SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
            : CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }
        else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
        {
            ParityTable256[*pHIrda->pTxBuffPtr]
            ? CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
            : SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
        }
    }
    WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);
    pHIrda->TxXferCount--;
    pHIrda->pTxBuffPtr++;


    while( (pHIrda->TxXferCount || pHIrda->RxXferCount) &&
            ((HAL_GetTick() - tickstart) < Timeout) )
    {
        if( __HAL_UART_IRDA_GET_FLAG(pHIrda, UART_IRDA_FLAG_RXNE) &&
            pHIrda->RxXferCount )
        {
            *pHIrda->pRxBuffPtr = (uint8_t)pHIrda->Instance->SBUF;

            __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_RXNE);

            if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
                pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
            {
                if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
                {
                    READ_BIT(pHIrda->Instance->SCON, UART_SCON_RB8) ? (check = 1U) : (check = 0U);
                }
                else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
                {
                    READ_BIT(pHIrda->Instance->SCON, UART_SCON_TB8) ? (check = 0U) : (check = 1U);
                }

                if( ParityTable256[*pHIrda->pRxBuffPtr] != check )
                {
                    pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_PARITY;
                }
            }

            pHIrda->RxXferCount--;
            pHIrda->pRxBuffPtr++;
        }

        if( __HAL_UART_IRDA_GET_FLAG(pHIrda, UART_IRDA_FLAG_TC) &&
            pHIrda->TxXferCount )
        {
            __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

            if( pHIrda->Init.WordLength == UART_IRDA_WORDLENGTH_9B &&
                pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
            {
                if( pHIrda->Init.Parity == UART_IRDA_PARITY_EVEN )
                {
                    ParityTable256[*pHIrda->pTxBuffPtr]
                    ? SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
                    : CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
                }
                else if( pHIrda->Init.Parity == UART_IRDA_PARITY_ODD )
                {
                    ParityTable256[*pHIrda->pTxBuffPtr]
                    ? CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8)
                    : SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
                }
                else
                {
                    CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);
                }
            }

            WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);

            pHIrda->TxXferCount--;
            pHIrda->pTxBuffPtr++;
        }
    }

    rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_TC, RESET, tickstart, Timeout);

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, (UART_IRDA_IT_RIEN | UART_IRDA_IT_TIEN));

    pHIrda->gState  = HAL_UART_IRDA_STATE_READY;
    pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

    if( rval != HAL_OK || pHIrda->TxXferCount || pHIrda->RxXferCount )
    {
        rval = HAL_TIMEOUT;
    }
    if( pHIrda->ErrorCode != HAL_UART_IRDA_ERROR_NONE )
    {
        rval = HAL_ERROR;
    }

    __HAL_UNLOCK(pHIrda);

    return rval;
}


/**
  * @brief  Address the communication and send a set of data in blocking mode.
  * @param  pHIrda     Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                  the configuration information for the specified UART IrDA module.
  * @param  slaveAddr  Addressing slave value
  * @param  pData    Pointer to transmit data buff.
  * @param  Size     Amount of data elements to be sent.
  * @param  Timeout  Timeout duration.
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Transmit_Addressing(UART_IRDA_HandleTypeDef *pHIrda, uint8_t slaveAddr,
                                                    uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    HAL_StatusTypeDef rval = HAL_OK;

    uint32_t tickstart = 0U;

    if( !pHIrda || !pData || !Size || !Timeout )
    {
        return HAL_ERROR;
    }

    if( pHIrda->Init.WordLength != UART_IRDA_WORDLENGTH_9B ||
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        return HAL_ERROR;
    }

    if( pHIrda->gState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->gState      = HAL_UART_IRDA_STATE_BUSY_TX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

    tickstart = HAL_GetTick();

    /* Send addressing data */
    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);

    WRITE_REG(pHIrda->Instance->SBUF, slaveAddr);

    rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_TC, RESET, tickstart, Timeout);
    if( rval != HAL_OK )
    {
        pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_TIMEOUT;

        pHIrda->gState = HAL_UART_IRDA_STATE_READY;

        __HAL_UNLOCK(pHIrda);

        return rval;
    }

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    pHIrda->TxXferCount     = Size;
    pHIrda->TxXferSize      = Size;
    pHIrda->pTxBuffPtr      = pData;

    /* Send normal data */
    while( pHIrda->TxXferCount )
    {
        CLEAR_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);

        WRITE_REG(pHIrda->Instance->SBUF, *pHIrda->pTxBuffPtr);

        rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_TC, RESET, tickstart, Timeout);
        if( rval != HAL_OK )
        {
            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_TIMEOUT;

            break;
        }

        __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

        pHIrda->TxXferCount--;
        pHIrda->pTxBuffPtr++;
    }

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

    pHIrda->gState = HAL_UART_IRDA_STATE_READY;

    __HAL_UNLOCK(pHIrda);

    return rval;
}


/**
  * @brief  Receive a set of data by addressing communication in blocking mode.
  * @param  pHIrda     Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                  the configuration information for the specified UART IrDA module.
  * @param  pData    Pointer to receive data buff.
  * @param  Size     Amount of data elements to be receive.
  * @param  Timeout  Timeout duration.
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Receive_Addressing(UART_IRDA_HandleTypeDef *pHIrda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    HAL_StatusTypeDef rval = HAL_OK;

    uint32_t tickstart = 0U;

    if( !pHIrda || !pData || !Size || !Timeout )
    {
        return HAL_ERROR;
    }

    if( pHIrda->Init.WordLength != UART_IRDA_WORDLENGTH_9B ||
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        return HAL_ERROR;
    }

    if( pHIrda->RxState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->RxState     = HAL_UART_IRDA_STATE_BUSY_RX_ADDRESS;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->RxXferCount = Size;
    pHIrda->RxXferSize  = Size;
    pHIrda->pRxBuffPtr  = pData;

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_RIEN);

    tickstart = HAL_GetTick();

    /* Wait for an addressing signal that matches its own address */
    rval = _UART_IRDA_WaitAddressingFlagUntilTimeout(pHIrda, tickstart, Timeout);
    if( rval != HAL_OK )
    {
        pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_TIMEOUT;

        pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

        __HAL_UNLOCK(pHIrda);

        return rval;
    }

    /* Receiving common data */
    pHIrda->RxState = HAL_UART_IRDA_STATE_BUSY_RX;

    while( pHIrda->RxXferCount )
    {
        rval = _UART_IRDA_WaitOnFlagUntilTimeout(pHIrda, UART_IRDA_FLAG_RXNE, RESET, tickstart, Timeout);
        if( rval != HAL_OK )
        {
            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_TIMEOUT;

            break;
        }

        *pHIrda->pRxBuffPtr = (uint8_t)pHIrda->Instance->SBUF;

        __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_RXNE);

        if( READ_BIT(pHIrda->Instance->SCON, UART_SCON_RB8) )
        {
            pHIrda->ErrorCode |= HAL_UART_IRDA_ERROR_PARITY;
        }

        pHIrda->RxXferCount--;
        pHIrda->pRxBuffPtr++;
    }

    if( pHIrda->ErrorCode & HAL_UART_IRDA_ERROR_PARITY )
    {
        rval = HAL_ERROR;
    }

    __HAL_UART_IRDA_DISABLE_IT(pHIrda, UART_IRDA_IT_RIEN);

    pHIrda->RxState = HAL_UART_IRDA_STATE_READY;

    __HAL_UNLOCK(pHIrda);

    return rval;
}


/**
  * @brief  Address the communication and send a set of data in non-blocking mode.
  * @param  pHIrda     Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                  the configuration information for the specified UART IrDA module.
  * @param  slaveAddr  Addressing slave value
  * @param  pData    Pointer to transmit data buff.
  * @param  Size     Amount of data elements to be sent.(The value of this number must be less than 0xffffU)
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Transmit_Addressing_IT(UART_IRDA_HandleTypeDef *pHIrda, uint8_t slaveAddr, uint8_t *pData, uint16_t Size)
{
    if( !pHIrda || !pData || !Size || (Size == 0xffffU) )
    {
        return HAL_ERROR;
    }

    if( pHIrda->Init.WordLength != UART_IRDA_WORDLENGTH_9B ||
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        return HAL_ERROR;
    }

    if( pHIrda->gState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->gState      = HAL_UART_IRDA_STATE_BUSY_TX;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->TxXferCount = (Size + 1);
    pHIrda->TxXferSize  = Size;
    pHIrda->pTxBuffPtr  = (pData--);

    #if defined(UART_INTDIS_TIDIS)
    __HAL_UART_IRDA_DISABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_TI);
    #endif  /* End of UART_INTDIS_TIDIS */

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_TC);

    SET_BIT(pHIrda->Instance->SCON, UART_SCON_TB8);

    WRITE_REG(pHIrda->Instance->SBUF, slaveAddr);

    __HAL_UNLOCK(pHIrda);

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_TIEN);

    return HAL_OK;
}


/**
  * @brief  Receive a set of data by addressing communication in non-blocking mode.
  * @param  pHIrda     Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                  the configuration information for the specified UART IrDA module.
  * @param  pData    Pointer to receive data buff.
  * @param  Size     Amount of data elements to be receive.
  * @param  Timeout  Timeout duration.
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_UART_IRDA_Receive_Addressing_IT(UART_IRDA_HandleTypeDef *pHIrda, uint8_t *pData, uint16_t Size)
{
    if( !pHIrda || !pData || !Size || !pHIrda->Instance->SADEN )
    {
        return HAL_ERROR;
    }

    if( pHIrda->Init.WordLength != UART_IRDA_WORDLENGTH_9B ||
        pHIrda->Init.Parity != UART_IRDA_PARITY_NONE )
    {
        return HAL_ERROR;
    }

    if( pHIrda->RxState != HAL_UART_IRDA_STATE_READY )
    {
        return HAL_BUSY;
    }

    /* Check input parameter */
    assert_param(IS_UART_IRDA_INSTANCE(pHIrda->Instance));
    assert_param(IS_UART_IRDA_BAUDRATE(pHIrda->Init.BaudRate));
    assert_param(IS_UART_IRDA_PARITY(pHIrda->Init.Parity));
    assert_param(IS_UART_IRDA_WORDLENGTH(pHIrda->Init.WordLength));

    __HAL_LOCK(pHIrda);

    pHIrda->RxState     = HAL_UART_IRDA_STATE_BUSY_RX_ADDRESS;
    pHIrda->ErrorCode   = HAL_UART_IRDA_ERROR_NONE;
    pHIrda->RxXferCount = Size;
    pHIrda->RxXferSize  = Size;
    pHIrda->pRxBuffPtr  = pData;

    __HAL_UART_IRDA_CLEAR_FLAG(pHIrda, UART_IRDA_FLAG_RXNE);

    #if defined(UART_INTDIS_RIDIS)
    __HAL_UART_IRDA_DISABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_RI);
    __HAL_UART_IRDA_DISABLE_INTDIS(pHIrda, UART_IRDA_INTDIS_FE);
    #endif  /* End of UART_INTDIS_RIDIS */

    __HAL_UNLOCK(pHIrda);

    SET_BIT(pHIrda->Instance->SCON, UART_SCON_SM2);

    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_FEEN);
    __HAL_UART_IRDA_ENABLE_IT(pHIrda, UART_IRDA_IT_RIEN);

    return HAL_OK;
}


/**
  * @brief  Returns the UART IrDA state.
  * @param  pHIrda   Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                the configuration information for the specified UART IrDA module.
  * @retval HAL state
  */
uint32_t HAL_UART_IRDA_GetState(UART_IRDA_HandleTypeDef *pHIrda)
{
    return (uint32_t)(pHIrda->gState | pHIrda->RxState);
}

/**
  * @brief  Return the UART IrDA error code
  * @param  pHIrda  Pointer to a UART_IRDA_HandleTypeDef structure that contains
  *                the configuration information for the specified UART IrDA.
  * @retval UART IrDA Error Code
  */
uint32_t HAL_UART_IRDA_GetError(UART_IRDA_HandleTypeDef *pHIrda)
{
    return (uint32_t)pHIrda->ErrorCode;
}



/** End of UART_Exported_Functions
 * @}
 */





/** End of UART_IrDA HAL module driver
 * @}
 */

#endif  /* End of HAL_UART_IRDA_MODULE_ENABLED */

